<!DOCTYPE html>
<html lang="zh-Hans">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>GitXDBDemo</title>
    <script src="https://unpkg.com/vue@next"></script>

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css">
    <style>
        .width-control-desc {
            width: 6em;
        }
        .desc-label {
            display: flex;
            justify-content: flex-end;
        }
        .typebackground {
            background-position: 99% 1%;
            background-size: 50px 50px;
            background-repeat: no-repeat;
        }
        .gitee-img {
            background-image: url(https://gitee.com/assets/favicon.ico)
        }
        .github-img {
            background-image: url(https://ae01.alicdn.com/kf/H2fc84859291347418b11091fe0e508b8v.png)
        }
        .comment-item {
            display: flex;
            flex-direction: column;
            justify-content: center;
        }
        .comment-operation {
            align-self: flex-end;
        }
    </style>
</head>

<body class="container">
    <div id="root">
        <div :class="['card', 'typebackground', 'mt-2', currentUserInfo ? '' : `${type}-img`]" :style="{'background-image': currentUserInfo && `url(${currentUserInfo.avatar_url})`}">
            <!-- <img src="..." class="card-img-top" alt="..."> -->
            <div class="card-body">
              <h5 class="card-title"><a :href="currentRepoLink">GitXDB Demo</a></h5>
              <p class="card-text"> 
                <div class="btn-group" role="group">
                    <button id="btnGroupDrop1" type="button" class="btn btn-secondary dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
                        使用 <code>{{type}}</code> API
                    </button>
                    <div class="dropdown-menu" aria-labelledby="btnGroupDrop1">
                      <a class="dropdown-item" @click="type = 'gitee'">gitee</a>
                      <a class="dropdown-item" @click="type = 'github'">github</a>
                    </div>
                </div>将指定仓库的 issue 作为简单的表进行数据存储更改等。
                <a href="https://github.com/apps/gitxdbapp" v-if="type === 'github'">首次使用需要安装应用</a>
            </p>
              <div class="input-group">
                <div class="input-group-prepend">
                    <span class="input-group-text width-control-desc desc-label">仓库库主</span>
                </div>
                <input class="form-control" v-model="settings.owner">
              </div>
              <div class="input-group">
                <div class="input-group-prepend">
                    <span class="input-group-text width-control-desc desc-label">仓库名称</span>
                </div>
                <input class="form-control" v-model="settings.repo">
              </div>
              <div class="input-group" v-if="authInfo.code">
                <div class="input-group-prepend">
                    <span class="input-group-text width-control-desc desc-label">CODE</span>
                </div>
                <input class="form-control" :value="authInfo.code">
              </div>
              <div class="input-group">
                <div class="input-group-prepend">
                    <span class="input-group-text width-control-desc desc-label">授权码</span>
                </div>
                <input class="form-control" v-model="settings.access_token">
              </div>
              
              <div class="mt-2 d-flex justify-content-end">
                <button class="btn btn-primary" @click="doSettings" v-if="!authInfo.code && !settings.access_token">开始授权</button>
                <button class="ml-2 btn btn-primary" @click="doSettings" v-if="authInfo.code && !settings.access_token">完成授权</button>
                <button class="ml-2 btn btn-primary" @click="begindemo" v-if="settings.access_token">开始体验</button>
                <!-- <button class="ml-2 btn btn-info" @click="usemine" v-if="settings.access_token && changed">使用我的</button> -->
                <button class="ml-2 btn btn-danger" @click="exit" v-if="settings.access_token">退出</button>
              </div>
            </div>
          </div>
        <div v-show="startDemo">
        <h5 class="mt-2">All ISSUES:</h5>
        <ul class="list-group">
            <template v-for="(table, name) in allIssues" :key="table.number">
                <li class="list-group-item" :title="table.title"><a :href="table.html_url" target="_blank">{{name}}</a>：{{table.body}}</li>
            </template>
        </ul>

        <div>
            <div class="row">
                <div class="mt-2 col-12 col-sm-12 col-md-4 d-flex justify-content-center">
                    <div class="dropdown" style="min-width: 5em">
                        <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-expanded="false">
                          与表 {{addComment.issueName || '选择表'}} 进行交互
                        </button>
                        <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
                          <a class="dropdown-item"  @click="addComment.issueName = table.title" v-for="table in allIssues">{{table.title}}</a>
                        </div>
                    </div>
                </div>
                <div class="mt-2 col-6 col-sm-6 col-md-4 d-flex justify-content-center"><button class="btn btn-primary" @click="addCommentFn">增加一条数据</button></div>
                
                <div class="mt-2 col-6 col-sm-6 col-md-4 d-flex justify-content-center"><button class="btn btn-primary" @click="getAllCommentFn">获取所有评论</button></div>
            </div>
        </div>
        
        
        <div class="input-group mt-2">
            <div class="input-group-prepend">
                <span class="input-group-text">内容</span>
            </div>
            <input class="form-control" v-model="addComment.content">
        </div>
        <h5 class="mt-2">从表[{{addComment.issueName ? `${addComment.issueName}` : ''}}]中查询数据</h5>
        <div class="list-group">
            <li v-for="comment in allComments" :key="comment.id" class="list-group-item comment-item">
                {{comment.body}}
                <div class="comment-operation">
                    <img :src='comment.user.avatar_url' style="border-radius:10px;width:20px;height: 20px;" :title='comment.user.name'/>
                    <template v-if="comment.user.id === currentUserInfo.id">
                        <button class="ml-1 btn btn-sm" @click="updateComment(comment.id)">✍</button>
                        <button class="ml-1 btn btn-sm" @click="deleteComment(comment.id)">➖</button>
                    </template>
                </div>
            </li>
        </div>
        </div>
    </div>
    <script src="./dist/gitdb_bundle.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.bundle.min.js"></script>
    <script>
        // 本地环境通常带端口号，而生产环境并不带，以此设置 test 标志。
        var test = window.location.port !== '';
        if (test) {
            console.log("%ctest mode", "background: gray; color: white; padding: 2px 5px;")
        }
       
        var onceFlag = true

        let defaultType = "gitee";
        if (location.href.indexOf('github.io') !== -1) {
            defaultType = "github"
        }
        const tokenName = {
            'gitee': 'giteedb_access_token',
            'github': 'githubdb_access_token',
        }
        const host = {
            'gitee': 'https://gitee.com/api/v5',
            'github': 'https://api.github.com'
        }

        const giteeConsts = {
            owner: "lhhcherry",
            redirect_uri: 'https://lhhcherry.gitee.io/ssmell/',
            client_id: 'e8db1dcfd00bf405429813d2703cbf10f99b4ae204fcf01385dfb2e484e8d3be',
            auth_url_base: "https://gitee.com/oauth",
        }
        const githubConsts = {
            owner: 'smart-town',
            client_id: 'Iv1.bbd60b3d2083e187',
            auth_url_base: "https://github.com/login/oauth",
            redirect_uri: "https://smart-town.github.io/gitx-simple-db/",
        }

        if (test) {
            console.log("test mode, set redirect_uri")
            giteeConsts.redirect_uri = githubConsts.redirect_uri = 'http://192.168.31.8:8000/'
        }
        const Default = {
            gitee: giteeConsts,
            github: githubConsts,
        }
        // const getAccessTokenUrl = 'https://service-osylcc6l-1302417315.cd.apigw.tencentcs.com/release' + '/access_token'
        const getAccessTokenUrl = test ? 'http://192.168.31.8:5000/access_token' : 'https://service-osylcc6l-1302417315.cd.apigw.tencentcs.com/release/access_token'


        const reset = function () {
            window.location.replace(window.location.href.replace(/\?.*/, ""))
        }
        function loadToken(type=defaultType) {
            let token_name = tokenName[type]
            let token = localStorage.getItem(token_name)
            if (!token || !token.trim()) {
                return 
            }

            let tokenExpired = localStorage.getItem(`${token_name}_expired`)
            let expiredDate = parseInt(tokenExpired)
            let current = new Date().getTime()
            if (current > expiredDate) {
                console.log("expired, use refresh_token is in the progress.")
                return "";
            } else {
                return token
            }
        }
        const DemoOptions = {
            data() {
                return {
                    type: defaultType,
                    data: '',
                    allIssues: {},
                    addComment: {
                        issueName: '',
                        content: ''
                    },
                    allComments: [],
                    settings: {
                        owner: Default[defaultType].owner,
                        repo: 'gitx-simple-db',
                        access_token: loadToken(defaultType),
                    },
                    authInfo: {
                        code: '',
                        state: '',
                    },
                    currentRepoLink: defaultType === 'gitee' ? 'https://gitee.com/lhhcherry/gitx-simple-db' : 'https://github.com/smart-town/gitx-simple-db',
                    startDemo: false,
                    currentUserInfo: null,
                    gitdb: null,
                }
            },
            watch: {
                type: function(newV) {
                    this.startDemo = false
                    this.settings.access_token = loadToken(this.type)
                    if (!this.settings.access_token) {
                        this.dealSearchParams()
                    }
                    this.settings.owner = Default[newV].owner
                },
                
            },
            methods: {
                usemine: async function() {
                    try {
                        this.settings.owner = this.currentUserInfo.login
                        let repos = await this.gitdb.fetch.rawRequest(this.currentUserInfo.repos_url, {body: {sort: 'updated', type: 'owner'}, method: 'GET'})
                        if (repos.length) {
                            this.settings.repo = repos[0].name
                        } else {
                            alert("useful repo: 0")
                        }
                    } catch (e) {
                        console.error(e)
                    }
                },
                dealSearchParams: function() {
                    if (window.location.search) {
                        let searchParams = new URLSearchParams(window.location.search)
                        let code = searchParams.get("code")
                        let state = searchParams.get("state")
                        if (code && state) {
                            this.authInfo = {code, state}
                            window.history.pushState(JSON.stringify(this.authInfo), "", window.location.href.replace(/\?.*/, ""))
                        }
                    }
                },
                deleteComment: function(id) {
                    console.log("prepare delte id:", id)
                    if(window.confirm("确认删除该条评论?")) {
                        this.gitdb.deleteData(id).then(v => {
                            alert("delete success!")
                            this.getAllCommentFn()
                        }).catch(e => {
                            alert(e.message || e.error_description || e.error || '删除失败')
                        })
                    }
                },
                updateComment: function(id) {
                    if (window.confirm("确认更新?") && this.addComment.content) {
                        this.gitdb.updateData(id, this.addComment.content).then(v => {
                            alert("update success!")
                            this.getAllCommentFn()
                        }).catch(e => {
                            alert(e.message || e.error_description || e.error || '删除失败')
                        })
                    }
                },
                begindemo: async function() {
                    let shouldCreate = true
                    if (this.gitdb) {
                        let {repo, owner} = this.gitdb.options
                        shouldCreate = repo !== this.settings.repo || owner !== this.settings.owner
                        if (shouldCreate) {
                            this.gitdb.options.repo = this.settings.repo
                            this.gitdb.options.owner = this.settings.owner
                        }
                    }
                    if (shouldCreate) {
                        this.gitdb = gitdb.GitXSimpleDB.getInstance({
                            option: {...this.settings, hostBase: host[this.type]},
                            newForce: true,
                        })
                        console.log("created gitdb:", this.gitdb)

                    }
                    try {
                        let user = await this.gitdb.fetch.rawRequest(`${host[this.type]}/user`, {})
                        this.currentUserInfo = user
                        await this.getAllIssues()
                    } catch (e) {
                        console.error(e)
                        alert(e.message || e.error_description || e.error || "初始化失败")
                    }
                },
                getAllIssues: function() {
                    this.gitdb.allTables().then(v => {
                        console.log("allTables:", v)
                        this.allIssues = this.gitdb.global.tables
                        let allIssuesName = Object.keys(this.allIssues)
                        if (!allIssuesName.length) {
                            if (this.created) {
                                window.alert("已创建成功，请刷新后重试")
                                reset()
                                return;
                            }
                            let sure = window.confirm("No issues, Auto create one?")
                            if (!sure) return
                            this.addTable("gixdb_demo", "^_^").then(v => {
                                this.created = true
                                this.getAllIssues()
                            }).catch(e => {
                                alert(e.message || e.error_description || "create err")
                            })
                        } else { 
                            this.addComment.issueName = allIssuesName[0]
                        }
                        this.startDemo = true
                    }).catch(e => {
                        console.error(e)
                        if (e.message && e.message.indexOf("Failed to fetch") !== -1) {
                            reset()
                        }
                        
                        alert(`Not authorized or repo [${this.settings.owner}/${this.settings.repo}] not exists.`)
                        let use = window.confirm("Auto Use your repo?")
                        if (!use) {
                            reset()
                        } else {
                            this.usemine()
                        }
                    })
                },
                addTable: async function(name, body) {
                    await this.gitdb.createTable(name, body)
                },
                addCommentFn: function(e) {
                    let tableName = this.addComment.issueName
                    if (this.allIssues[tableName] && this.addComment.content) {
                        this.gitdb.addData(tableName, this.addComment.content)
                            .then(v => {
                                alert("add success!")
                                this.getAllCommentFn()
                            })
                            .catch(e => {
                                alert(e.message || e.error_description || "add error")
                            })
                    } else {
                        console.error(`table: [${tableName}]not exist!`)
                    }
                },
                getAllCommentFn: function() {
                    let tableName = this.addComment.issueName
                    if (this.allIssues[tableName]) {
                        this.gitdb.queryDataByPage(tableName, 1, 20).then(data => {
                            this.allComments = data
                        }).catch(e => {
                            console.error('get all comments err:', e)
                        })
                    } else {
                        console.error(`table: [${tableName}]not exist!`)
                    }
                },
                doSettings: function() {
                    const state = "GITXDB"
                    const {client_id, redirect_uri, auth_url_base,} = Default[this.type]
                    
                    let authUrl = `${auth_url_base}/authorize?client_id=${client_id}&redirect_uri=${redirect_uri}&response_type=code&state=${state}`;
                    if (this.type === 'github') {
                        authUrl = `${auth_url_base}/authorize?client_id=${client_id}&redirect_uri=${redirect_uri}&state=${state}`
                    }
                    
                    if (!this.authInfo.code) {
                        window.location.assign(authUrl)
                    } else {
                        let data = {
                            type: this.type,
                            code: this.authInfo.code,
                        }
                        if (this.type === 'gitee') {
                            data['redirect_uri'] = redirect_uri
                        }
                        fetch(getAccessTokenUrl + `?${new URLSearchParams(data).toString()}`).then(async v => {
                            if (v.status !== 200) {
                                console.log("resp raw:", v)
                            }
                            try {
                                text = await v.text()
                                return JSON.parse(text)
                            } catch(e) {
                                console.log(e)
                                return text
                            }
                        }).then(v => {
                            if (v.access_token) {
                                this.settings.access_token = v.access_token
                                if (this.type === 'gitee') {
                                    localStorage.setItem("giteedb_access_token", v.access_token)
                                    localStorage.setItem("giteedb_access_token_expired", (v.created_at + v.expires_in) * 1000)
                                    localStorage.setItem("giteedb_access_token_refresh", v.refresh_token)
                                    localStorage.setItem("giteedb_access_token_scope", v.scope)
                                } else if (this.type === 'github'){
                                    localStorage.setItem("githubdb_access_token", v.access_token)
                                    localStorage.setItem("githubdb_access_token_scope", v.scope)
                                    localStorage.setItem("githubdb_access_token_expired", new Date().getTime() + v.expires_in * 1000)
                                    localStorage.setItem("githubdb_access_token_refresh", v.refresh_token)
                                    localStorage.setItem("githubdb_access_token_refresh_expired", v.refresh_token_expires_in * 1000)
                                } else {
                                    alert("not support type:", this.type)
                                }
                            } else {
                                throw v
                            }
                        }).catch(e => {
                            console.log("request accesstoken err", e)
                            let errorInfo = e.message || e.error_description || e.error || "Something Error"
                            alert(errorInfo)
                            if (errorInfo.indexOf("expired") !== -1 || errorInfo.indexOf("过期") !== -1)
                            window.location.reload()
                        })
                    }
                },
                exit() {
                    let deltedKeys = ['_access_token', '_access_token_expired', '_access_token_refresh', '_access_token_scop']
                    let prefix = this.type + 'db'
                    deltedKeys.forEach(v => {
                        key = prefix + v;
                        console.log("delelete key:", key)
                        localStorage.removeItem(key)
                        reset()
                    })
                }
            },
            created() {
                if (!this.settings.access_token) {
                    this.dealSearchParams()
                }
            },
            mounted() {
                if (onceFlag) {
                    $('[data-toggle="tooltip"]').tooltip()
                    onceFlag = false
                }
            }
        }
        const app = Vue.createApp(DemoOptions)


        app.mount("#root")
    </script>
</body>

</html>